package com.inetools.gwetons.client;

import java.util.logging.Level;

import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.core.client.JavaScriptObject;
import com.inetools.gwetons.client.logging.JsniLogUtilAdapterTemplate;
import com.inetools.gwetons.shared.logging.LogUtil;
import com.inetools.gwetons.shared.logging.LogUtilFactoryIntf;

/**
 * This wrapper class over JavaScript's cssRule object make the found cssRule objects by addStyleSelector 
 * method in CssStyleChangerBySelector class accessible from outside class object.
 * @author ay
 *
 */
public class JsCssRule extends JsniLogUtilAdapterTemplate {
	@Override
	protected String getNameForLogging() {
		return this.getClass().getName();
	}

	final JavaScriptObject cssRule;
	public JsCssRule( JavaScriptObject cssRule, LogUtil logUtil) {
		setLogUtil( logUtil);
		
		LogUtil ownLogUtil = getLogUtil();
		ownLogUtil.entering( "Constructor", new Object[]{ "cssRule(=" + cssRule.toString() + ")"});
		
		this.cssRule = cssRule;
		
		ownLogUtil.exiting( "Constructor");
	}
	public JsCssRule( JavaScriptObject cssRule, LogUtilFactoryIntf logUtilFactoryIntf) {
		setLogUtilFactoryIntf( logUtilFactoryIntf);
		
		LogUtil logUtil = getLogUtil();
		logUtil.entering( "Constructor", new Object[]{ "cssRule(=" + cssRule.toString() + ")"});
		
		this.cssRule = cssRule;
		
		logUtil.exiting( "Constructor");
	}
	public JsCssRule( JavaScriptObject cssRule) {
		this( cssRule, (LogUtil)null);
//TODO may reinitialize logUtilFactoryInterface member field and logUtil member field 
	}
	
	/**
	 * @return 
	 * Note: IE will return the selectorText value with upper-case characters.
	 */
	native String obtainSelectorText( JavaScriptObject cssRuleObj) throws JavaScriptException /*-{
//		var cssRuleObj = instance.@com.inetools.gwetons.client.JsCssRule::cssRule;
		return cssRuleObj.selectorText;
	}-*/;
	/**
	 * @return 
	 * Note: IE will return the selectorText value with upper-case characters.
	 */
	public String getSelectorText() {
		return obtainSelectorText( this.cssRule);
	}
	native String obtainStyle( JavaScriptObject cssRuleObj) throws JavaScriptException /*-{
//		var cssRuleObj = instance.@com.inetools.gwetons.client.JsCssRule::cssRule;
		if ( !cssRuleObj.style) return null;
		return new String( cssRuleObj.style);
	}-*/;
	public String getStyle() {
		return obtainStyle( this.cssRule);
	}
	
	native void setStyle( String styleStr, String valueStr, JavaScriptObject cssRuleObj) 
	throws JavaScriptException /*-{
		if ( !styleStr) return;
		if ( "" == styleStr) return;
		if ( !valueStr) return;
		if ( "" == valueStr) return;
		
//		var cssRuleObj = instance.@com.inetools.gwetons.client.JsCssRule::cssRule;
		if ( cssRuleObj.style){
			cssRuleObj.style[ styleStr] = valueStr;
		}
	}-*/;
	public void setStyle( String styleStr, String valueStr) {
		setStyle( styleStr, valueStr, this.cssRule);
	}
	
	native void dumpCssRule( JavaScriptObject cssRuleObj) 
	throws JavaScriptException /*-{
		// Preparations for logging ---------------------------------------------------------------
		var methodName = "dumpCssRule JSNI";
		var thisJsniLogUtil = this.@com.inetools.gwetons.client.JsCssRule::getJsniLogUtil()();
		var jsniLogEntering
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getEnteringFunction()();
		var jsniLogging
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getLogFunction()();
		var jsniLogExiting
		= thisJsniLogUtil.@com.inetools.gwetons.client.logging.JsniLogUtil::getExitingFunction()();
		// ----------------------------------------------------------------------------------------
		
		jsniLogEntering( methodName, [ "cssRuleObj(=" + String( cssRuleObj) + ")"]);
		
try {		 
		for( var propertyIndex in cssRuleObj) {
			jsniLogging(
				@java.util.logging.Level::FINEST,
				"Dumping about " + propertyIndex + " property of cssRuleObj:" 
				);
			if ( cssRuleObj.hasOwnProperty( String( propertyIndex))) {
				jsniLogging(
					@java.util.logging.Level::FINEST,
					"cssRuleObj.hasOwnProperty( " + propertyIndex + ") = " 
					+ String( cssRuleObj.hasOwnProperty( String( propertyIndex))) 
					);
			}
			jsniLogging(
				@java.util.logging.Level::FINEST,
				"typeof( cssRuleObj[ "+ propertyIndex +"]) = " + String( typeof( cssRuleObj[ propertyIndex])) 
				);
			
			if ( propertyIndex == "style") {
				for( var styleIndex in cssRuleObj[ propertyIndex]) {
					if ( cssRuleObj[ propertyIndex].hasOwnProperty( String( styleIndex))) {
						jsniLogging(
							@java.util.logging.Level::FINEST,
							"cssRuleObj[ "+ propertyIndex +"].hasOwnProperty( " + styleIndex + ") = " 
							+ String( cssRuleObj[ propertyIndex].hasOwnProperty( String( styleIndex))) 
							);
					}
//TODO Research how to detect running on HtmlUnit and wrap by the if block conditioning HtmlUnit case					
					if ( styleIndex == "cssText") {
					// HtmlUnit Bug: it cannot dump the value and cssText shouldn't be under style property level as well.  
						continue; //for
					}
					if ( ( styleIndex == "paddingTop") || ( styleIndex == "paddingLeft") 
							|| ( styleIndex == "paddingBottom") || ( styleIndex == "paddingRight")
						) 
					{
					// HtmlUnit Bug: it cannot dump the value
						continue; //for
					}
					if ( ( styleIndex == "marginBottom") || ( styleIndex == "marginLeft") 
							|| ( styleIndex == "marginTop") || ( styleIndex == "marginRight")
						) 
					{
					// HtmlUnit Bug: it cannot dump the value
						continue; //for
					}
					
					jsniLogging(
						@java.util.logging.Level::FINEST,
						"typeof( cssRuleObj[ "+ propertyIndex +"][" + styleIndex + "]) = " 
						+ String( typeof( cssRuleObj[ propertyIndex][ styleIndex])) 
						);
					jsniLogging(
						@java.util.logging.Level::FINEST,
						"cssRuleObj[ " + propertyIndex + "][ " + styleIndex + "] = " 
						+ String( cssRuleObj[ propertyIndex][ styleIndex])
						);
				} // for
			}
			else {
				jsniLogging(
					@java.util.logging.Level::FINEST,
					"cssRuleObj[ " + propertyIndex + "] = " + String( cssRuleObj[ propertyIndex])
					);
			}
		} // for
}
catch( error) {
	jsniLogging( 
		@java.util.logging.Level::WARNING, 
		"Failure in logging property of cssRuleObj: " + String( error)
		);
	throw error;
}

		jsniLogExiting( methodName);
	}-*/;
	
	public boolean equals( JavaScriptObject cssRuleObj) {
		String methodName = "equals";
		LogUtil logUtil = getLogUtil();
		
		logUtil.entering( methodName, new Object[]{ "cssRuleObj(=" + cssRuleObj.toString() + ")"});
		
		logUtil.log( Level.FINER, 
				"compareJavaScriptObjects result: " 
				+ JavaScriptObjectUtil.compareJavaScriptObjects( this.cssRule, cssRuleObj));
		
		logUtil.log( Level.FINER, "Dumping cssRuleObj input");
		dumpCssRule( cssRuleObj);
		logUtil.log( Level.FINER, "Dumping cssRule member field");
		dumpCssRule( this.cssRule);
		
		boolean result = this.cssRule.equals( cssRuleObj);
		
		logUtil.exiting( methodName, result);
		return result;
	}
}
